// OrderDlg.cpp : implementation file
//

#include "stdafx.h"
#include "LightspeedTraderAPIDemo.h"
#include "OrderDlg.h"
//#include "afxdialogex.h"

#include "ExecutionDlg.h"

enum STATIC_ORDER_VALUES {
	REFERENCE_ID,
	ORDER_ID,
	SYMBOL,
	TRADE_SIDE,
	ORIGINAL_SHARES,
	ORIGINAL_PRICE,
	ORIGINAL_MARKET,
	ORIGINAL_CONTRA,
	MARKET,
	CONTRA,
	IS_MARKET_ORDER,
	TIF,
	IS_HIDDEN,
	VISIBLE_SHARES,
	SECONDARY_PRICE,
	ACTIVE_SHARES,
	MARKET_PRICE,
	CREATE_TIME,
	CANCEL_TIME,
	CREATE_TIME_MILLIS,
	RECEIVE_TIME_MILLIS,
	CANCEL_CREATE_TIME_MILLIS,
	CANCEL_TIME_MILLIS,
	CANCEL_INITIATED,
	EXCHANGE,
	MARGIN_REQUIREMENT,
	BP_TYPE,

	END_STATIC_VALUES
};

enum DYNAMIC_ORDER_VALUES {
	EXECUTED_SHARES = END_STATIC_VALUES,
	REJECTED_SHARES,
	KILLED_SHARES,
	TOTAL_PRICE,
	AVERAGE_PRICE,
	CLOSED_PL,
	CLOSED_PL_AVE,
	ADDED_LIQUIDITY,
	ADDED_LIQUIDITY_EXECUTIONS,
	REMOVED_LIQUIDITY,
	REMOVED_LIQUIDITY_EXECUTIONS,

	END_DYNAMIC_VALUES
};


// OrderDlg dialog

IMPLEMENT_DYNAMIC(OrderDlg, CModelessDialog)

OrderDlg::OrderDlg(L_Position *p /*=NULL*/, CWnd* pParent /*=NULL*/)
	: CModelessDialog(OrderDlg::IDD, pParent)
	, account(NULL)
	, position(p)
	, order(NULL)
	, m_OrderDataListCtrl(CListCtrl())
	, m_OrderCombo(CComboBox())
	, m_OrderSearchType(REFERENCE_ID)
	, m_OrderDispType((p?ACTIVE_ORDERS:ALL_ORDERS))
{
	SetAPIFunctions();
}

OrderDlg::~OrderDlg()
{
	if (account)
	{
		account->L_Detach(this);
		account = NULL;
	}
	if (position)
	{
		position = NULL;
	}
	if (order)
	{
		order = NULL;
	}
}

BOOL OrderDlg::Create(CWnd *pParentWnd /*= CWnd::FromHandle(L_GetMainWnd())*/)
{
	return __super::Create(OrderDlg::IDD, pParentWnd);
}

void OrderDlg::DoDataExchange(CDataExchange* pDX)
{
	__super::DoDataExchange(pDX);

	DDX_Control(pDX, IDC_ORDERCOMBO, m_OrderCombo);
	DDX_Control(pDX, IDC_ORDERLIST, m_OrderDataListCtrl);
	DDX_Radio(pDX, IDC_REFIDRADIO, m_OrderSearchType);
	DDX_Radio(pDX, IDC_ALLRADIO, m_OrderDispType);
}

void OrderDlg::UpdateOrderCombo()
{
	//clear the contents first
	while (m_OrderCombo.GetCount() > 0)
	{
		m_OrderCombo.DeleteString(0);
	}

	bool iteratorsSet = false;
	order_iterator it, itend;

	if (position)
	{
		iteratorsSet = true;
		switch(m_OrderDispType)
		{
		case ACTIVE_ORDERS:
			it = position->active_orders_begin();
			itend = position->active_orders_end();
			break;
		case ACTIVE_BUY_ORDERS:
			it = position->active_orders_buy_begin();
			itend = position->active_orders_buy_end();
			break;
		case ACTIVE_SELL_ORDERS:
			it = position->active_orders_sell_begin();
			itend = position->active_orders_sell_end();
			break;
		default:
			iteratorsSet = false;
			break;
		}
	}
	else if (account)
	{
		switch(m_OrderDispType)
		{
		case ALL_ORDERS:
			it = account->orders_begin();
			itend = account->orders_end();
			break;
		case BUY_ORDERS:
			it = account->orders_buy_begin();
			itend = account->orders_buy_end();
			break;
		case SELL_ORDERS:
			it = account->orders_sell_begin();
			itend = account->orders_sell_end();
			break;
		case ACTIVE_ORDERS:
			it = account->active_orders_begin();
			itend = account->active_orders_end();
			break;
		case ACTIVE_BUY_ORDERS:
			it = account->active_orders_buy_begin();
			itend = account->active_orders_buy_end();
			break;
		case ACTIVE_SELL_ORDERS:
			it = account->active_orders_sell_begin();
			itend = account->active_orders_sell_end();
			break;
		}
		iteratorsSet = true;
	}

	if (iteratorsSet)
	{
		CString comboText;
		for (; it != itend; ++it)
		{
			switch(m_OrderSearchType)
			{
			case REFERENCE_ID:
				comboText.Format("%d", (*it)->L_ReferenceId());
				break;
			case ORDER_ID:
				comboText.Format("%d", (*it)->L_OrderId());
				break;
			}

			m_OrderCombo.AddString(comboText);
		}
	}
}

BOOL OrderDlg::OnInitDialog()
{
	__super::OnInitDialog();

	CString title;
	GetWindowText(title);
	title += " ";
	if (position)
	{
		title += "Position - ";
		title += position->L_Symbol();
	}
	else
	{
		title += "Account";
	}
	SetWindowText(title);

	if (position)
	{
		GetDlgItem(IDC_ALLRADIO)->EnableWindow(FALSE);
		GetDlgItem(IDC_BUYRADIO)->EnableWindow(FALSE);
		GetDlgItem(IDC_SELLRADIO)->EnableWindow(FALSE);
	}	

	DWORD style = m_OrderDataListCtrl.GetExtendedStyle();
	style |= LVS_EX_FULLROWSELECT;
	style |= LVS_EX_GRIDLINES;
	style |= LVS_EX_DOUBLEBUFFER;
	m_OrderDataListCtrl.SetExtendedStyle(style);

	m_OrderDataListCtrl.InsertColumn(0,"API Function", LVCFMT_LEFT, 120, 0);
	m_OrderDataListCtrl.InsertColumn(1,"Value", LVCFMT_LEFT, 120, 1);

	InitializeDataCtrlRows();

	account = L_GetAccount();
	account->L_Attach(this);

	UpdateOrderCombo();

	return TRUE;
}

void OrderDlg::InitializeDataCtrlRows()
{
	for (int i = 0; i < END_DYNAMIC_VALUES; ++i)
	{
		m_OrderDataListCtrl.InsertItem(i,APIFunctions[i]);
	}
}

void OrderDlg::UpdateStaticValues()
{
	m_OrderDataListCtrl.SetRedraw(FALSE); //disable redraw to reduce control flickering
	for (int i = 0; i < END_STATIC_VALUES; ++i)
	{
		m_OrderDataListCtrl.SetItemText(i, 1, GetTextForFunction(i));
	}
	m_OrderDataListCtrl.SetRedraw(TRUE);
}

void OrderDlg::UpdateDynamicValues()
{
	m_OrderDataListCtrl.SetRedraw(FALSE); //disable redraw to reduce control flickering
	for (int i = END_STATIC_VALUES; i < END_DYNAMIC_VALUES; ++i)
	{
		m_OrderDataListCtrl.SetItemText(i, 1, GetTextForFunction(i));
	}
	m_OrderDataListCtrl.SetRedraw(TRUE);
}

void OrderDlg::SetAPIFunctions()
{
	//clear APIFunction array
	memset(APIFunctions,NULL,sizeof(APIFunctions));

	strcpy_s(APIFunctions[REFERENCE_ID], "Reference ID");
	strcpy_s(APIFunctions[ORDER_ID], "Order ID");
	strcpy_s(APIFunctions[SYMBOL], "Symbol");
	strcpy_s(APIFunctions[TRADE_SIDE], "Trade Side");
	strcpy_s(APIFunctions[ORIGINAL_SHARES], "Original Shares");
	strcpy_s(APIFunctions[ORIGINAL_PRICE], "Original Price");
	strcpy_s(APIFunctions[ORIGINAL_MARKET], "Original Market");
	strcpy_s(APIFunctions[ORIGINAL_CONTRA], "Original Contra");
	strcpy_s(APIFunctions[MARKET], "Market");
	strcpy_s(APIFunctions[CONTRA], "Contra");
	strcpy_s(APIFunctions[IS_MARKET_ORDER], "Is Market Order");
	strcpy_s(APIFunctions[TIF], "TIF");
	strcpy_s(APIFunctions[IS_HIDDEN], "Is Hidden");
	strcpy_s(APIFunctions[VISIBLE_SHARES], "Visible Shares");
	strcpy_s(APIFunctions[SECONDARY_PRICE], "Secondary Price");
	strcpy_s(APIFunctions[ACTIVE_SHARES], "Active Shares");
	strcpy_s(APIFunctions[MARKET_PRICE], "Market Price");
	strcpy_s(APIFunctions[CREATE_TIME], "Create Time");
	strcpy_s(APIFunctions[CANCEL_TIME], "Cancel Time");
	strcpy_s(APIFunctions[CREATE_TIME_MILLIS], "Create Time Millis");
	strcpy_s(APIFunctions[RECEIVE_TIME_MILLIS], "Receive Time Millis");
	strcpy_s(APIFunctions[CANCEL_CREATE_TIME_MILLIS], "Cancel Create Time Millis");
	strcpy_s(APIFunctions[CANCEL_TIME_MILLIS], "Cancel Time Millis");
	strcpy_s(APIFunctions[CANCEL_INITIATED], "Cancel Initiated");
	strcpy_s(APIFunctions[REJECTED_SHARES], "Rejected Shares");
	strcpy_s(APIFunctions[KILLED_SHARES], "Killed Shares");
	strcpy_s(APIFunctions[CLOSED_PL], "Closed PL");
	strcpy_s(APIFunctions[CLOSED_PL_AVE], "Closed PL by Ave");
	strcpy_s(APIFunctions[EXCHANGE], "Exchange");
	strcpy_s(APIFunctions[MARGIN_REQUIREMENT], "Margin Requirement");
	strcpy_s(APIFunctions[BP_TYPE], "BP Type");
	strcpy_s(APIFunctions[EXECUTED_SHARES], "Excecuted Shares");
	strcpy_s(APIFunctions[TOTAL_PRICE], "Total Price");
	strcpy_s(APIFunctions[AVERAGE_PRICE], "Average Price");
	strcpy_s(APIFunctions[ADDED_LIQUIDITY], "Added Liquidity");
	strcpy_s(APIFunctions[ADDED_LIQUIDITY_EXECUTIONS], "Added Liquidity Executions");
	strcpy_s(APIFunctions[REMOVED_LIQUIDITY], "Removed Liquidity");
	strcpy_s(APIFunctions[REMOVED_LIQUIDITY_EXECUTIONS], "Removed Liquidity Executions");
}

CString OrderDlg::GetTextForFunction(int function)
{
	CString retString = "";

	switch(function)
	{
	case REFERENCE_ID:
		{
			retString.Format("%d", order->L_ReferenceId());
		}
		break;
	case ORDER_ID:
		{
			retString.Format("%d", order->L_OrderId());
		}
		break;
	case SYMBOL:
		{
			retString = order->L_Symbol();
		}
		break;
	case TRADE_SIDE:
		{
			retString = order->L_TradeSide();
		}
		break;
	case ORIGINAL_SHARES:
		{
			retString.Format("%d", order->L_OriginalShares());
		}
		break;
	case ORIGINAL_PRICE:
		{
			retString.Format("%.2f", order->L_OriginalPrice());
		}
		break;
	case ORIGINAL_MARKET:
		{
			retString = order->L_OriginalMarket();
		}
		break;
	case ORIGINAL_CONTRA:
		{
			retString = order->L_OriginalContra();
		}
		break;
	case MARKET:
		{
			retString = order->L_Market();
		}
		break;
	case CONTRA:
		{
			retString = order->L_Contra();
		}
		break;
	case IS_MARKET_ORDER:
		{
			if (order->L_IsMarketOrder())
			{
				retString = "Yes";
			}
			else
			{
				retString = "No";
			}
		}
		break;
	case TIF:
		{
			switch(order->L_TIF())
			{
			case L_TIF::IOC:
				retString = "IOC";
				break;
			case L_TIF::FOK:
				retString = "FOC";
				break;
			case L_TIF::DAY:
				retString = "DAY";
				break;
			default:
				retString.Format("%d", order->L_TIF());
				break;
			}
		}
		break;
	case IS_HIDDEN:
		{
			if (order->L_IsHidden())
			{
				retString = "Yes";
			}
			else
			{
				retString = "No";
			}
		}
		break;
	case VISIBLE_SHARES:
		{
			retString.Format("%d", order->L_VisibleShares());
		}
		break;
	case SECONDARY_PRICE:
		{
			retString.Format("%.2f", order->L_SecondaryPrice());
		}
		break;
	case ACTIVE_SHARES:
		{
			retString.Format("%d", order->L_ActiveShares());
		}
		break;
	case MARKET_PRICE:
		{
			retString.Format("%.2f", order->L_MarketPrice());
		}
		break;
	case CREATE_TIME:
		{
			retString.Format("%d", order->L_CreateTime());
		}
		break;
	case CANCEL_TIME:
		{
			retString.Format("%d", order->L_CancelTime());
		}
		break;
	case CREATE_TIME_MILLIS:
		{
			retString.Format("%d", order->L_CreateTimeMillis());
		}
		break;
	case RECEIVE_TIME_MILLIS:
		{
			retString.Format("%d", order->L_ReceiveTimeMillis());
		}
		break;
	case CANCEL_CREATE_TIME_MILLIS:
		{
			retString.Format("%d", order->L_CancelCreateTimeMillis());
		}
		break;
	case CANCEL_TIME_MILLIS:
		{
			retString.Format("%d", order->L_CancelTimeMillis());
		}
		break;
	case CANCEL_INITIATED:
		{
			if (order->L_CancelInitiated())
			{
				retString = "Yes";
			}
			else
			{
				retString = "No";
			}
		}
		break;
	case EXCHANGE:
		{
			retString = order->L_Exchange();
		}
		break;
	case MARGIN_REQUIREMENT:
		{
			retString.Format("%.2f", order->L_MarginRequirement());
		}
		break;
	case BP_TYPE:
		{
			switch(order->L_BPType())
			{
			case L_BPType::EQUITIESOPTIONS:
				retString = "EQUITIESOPTIONS";
				break;
			case L_BPType::FUTURES:
				retString = "FUTURES";
				break;
			case L_BPType::OPTIONS:
				retString = "OPTIONS";
				break;
			}
		}
		break;
	case EXECUTED_SHARES:
		{
			retString.Format("%d", order->L_ExecutedShares());
		}
		break;
	case REJECTED_SHARES:
		{
			retString.Format("%d", order->L_RejectedShares());
		}
		break;
	case KILLED_SHARES:
		{
			retString.Format("%d", order->L_KilledShares());
		}
		break;
	case TOTAL_PRICE:
		{
			retString.Format("%.2f", order->L_TotalPrice());
		}
		break;
	case AVERAGE_PRICE:
		{
			retString.Format("%.2f", order->L_AveragePrice());
		}
		break;
	case CLOSED_PL:
		{
			retString.Format("%.2f", order->L_ClosedPL());
		}
		break;
	case CLOSED_PL_AVE:
		{
			retString.Format("%.2f", order->L_ClosedPL());
		}
		break;
	case ADDED_LIQUIDITY:
		{
			retString.Format("%d", order->L_AddedLiquidity());
		}
		break;
	case ADDED_LIQUIDITY_EXECUTIONS:
		{
			retString.Format("%d", order->L_AddedLiquidityExecutions());
		}
		break;
	case REMOVED_LIQUIDITY:
		{
			retString.Format("%d", order->L_RemovedLiquidity());
		}
		break;
	case REMOVED_LIQUIDITY_EXECUTIONS:
		{
			retString.Format("%d", order->L_RemovedLiquidityExecutions());
		}
		break;
	}

	return retString;
}

//L_Oberver
void OrderDlg::HandleMessage(L_Message const *pMsg)
{
	switch(pMsg->L_Type())
	{
	case L_MsgOrderChange::id:
		{
			if (order)
			{
				L_MsgOrderChange const *pMsgOrderChange = static_cast<L_MsgOrderChange const *>(pMsg);
				if (order->L_ReferenceId() == pMsgOrderChange->L_ReferenceId())
				{
					UpdateDynamicValues();
				}
			}
			UpdateOrderCombo();
		}
		break;
	}
}

BEGIN_MESSAGE_MAP(OrderDlg, CModelessDialog)
	ON_WM_SIZE()
	ON_BN_CLICKED(IDC_REFIDRADIO, OnBnClickedRefIDRadio)
	ON_BN_CLICKED(IDC_ORDERIDRADIO, OnBnClickedOrderIDRadio)
	ON_BN_CLICKED(IDC_ALLRADIO, OnBnClickedAllRadio)
	ON_BN_CLICKED(IDC_BUYRADIO, OnBnClickedBuyRadio)
	ON_BN_CLICKED(IDC_SELLRADIO, OnBnClickedSellRadio)
	ON_BN_CLICKED(IDC_ACTIVERADIO, OnBnClickedActiveRadio)
	ON_BN_CLICKED(IDC_ACTIVEBUYRADIO, OnBnClickedActiveBuyRadio)
	ON_BN_CLICKED(IDC_ACTIVESELLRADIO, OnBnClickedActiveSellRadio)
	ON_CBN_SELCHANGE(IDC_ORDERCOMBO, OnCbnSelchangeOrderCombo)
	ON_COMMAND(ID_VIEW_EXECUTIONS, OnViewExecutions)
	ON_COMMAND(ID_FILE_CANCELORDER, OnFileCancelOrder)
END_MESSAGE_MAP()

// OrderDlg message handlers

void OrderDlg::OnSize(UINT nType, int cx, int cy)
{
	__super::OnSize(nType, cx, cy);

	ResizeControls();
}

void OrderDlg::ResizeControls()
{
	if (m_hWnd && m_OrderDataListCtrl.m_hWnd)
	{
		RECT Rect;
		GetClientRect(&Rect);

		RECT ctrlRect;
		m_OrderDataListCtrl.GetWindowRect(&ctrlRect);
		ScreenToClient(&ctrlRect);

		Rect.top = ctrlRect.top;

		m_OrderDataListCtrl.MoveWindow(&Rect);
	}
}

void OrderDlg::OnBnClickedOrderIDRadio()
{
	if (m_OrderSearchType != ORDER_ID)
	{
		m_OrderSearchType = ORDER_ID;
		UpdateOrderCombo();
	}
}

void OrderDlg::OnBnClickedRefIDRadio()
{
	if (m_OrderSearchType != REFERENCE_ID)
	{
		m_OrderSearchType = REFERENCE_ID;
		UpdateOrderCombo();
	}
}

void OrderDlg::OnBnClickedAllRadio()
{
	if (m_OrderDispType != ALL_ORDERS)
	{
		m_OrderDispType = ALL_ORDERS;
		UpdateOrderCombo();
	}
}

void OrderDlg::OnBnClickedBuyRadio()
{
	if (m_OrderDispType != BUY_ORDERS)
	{
		m_OrderDispType = BUY_ORDERS;
		UpdateOrderCombo();
	}
}

void OrderDlg::OnBnClickedSellRadio()
{
	if (m_OrderDispType != SELL_ORDERS)
	{
		m_OrderDispType = SELL_ORDERS;
		UpdateOrderCombo();
	}
}

void OrderDlg::OnBnClickedActiveRadio()
{
	if (m_OrderDispType != ACTIVE_ORDERS)
	{
		m_OrderDispType = ACTIVE_ORDERS;
		UpdateOrderCombo();
	}
}

void OrderDlg::OnBnClickedActiveBuyRadio()
{
	if (m_OrderDispType != ACTIVE_BUY_ORDERS)
	{
		m_OrderDispType = ACTIVE_BUY_ORDERS;
		UpdateOrderCombo();
	}
}

void OrderDlg::OnBnClickedActiveSellRadio()
{
	if (m_OrderDispType != ACTIVE_SELL_ORDERS)
	{
		m_OrderDispType = ACTIVE_SELL_ORDERS;
		UpdateOrderCombo();
	}
}

void OrderDlg::OnCbnSelchangeOrderCombo()
{
	long id;
	CString textID;
	m_OrderCombo.GetLBText(m_OrderCombo.GetCurSel(), textID);

	id = atol(textID.GetBuffer());

	switch(m_OrderSearchType)
	{
	case REFERENCE_ID:
		order = account->L_FindOrder(id);
		break;
	case ORDER_ID:
		order = account->L_FindOrderByOrderId(id);
		break;
	}

	if (order)
	{
		UpdateStaticValues();
		UpdateDynamicValues();
	}
}

void OrderDlg::OnViewExecutions()
{
	if (order)
	{
		ExecutionDlg *pDlg = new ExecutionDlg(order);

		if (! CLightspeedTraderAPIDemoApp::GetInstance()->CreateDlg(pDlg))
		{
			delete pDlg;
		}
	}
}

void OrderDlg::OnFileCancelOrder()
{
	if (account && order)
	{
		account->L_CancelOrder(order);
	}
}